<html>
   <head>
      <script src="../../../Grid/GridE.js"> </script>
   </head>
   <body class="Example">
      <style>
         /* Examples shared styles */
         .Example h1 { font:30px Arial; padding:5px 0px 5px 0px; margin:0px; text-align:center; }
         .Example h2 { font:15px Arial; padding:0px; margin:0px 0px 10px 0px; text-align:center; color:#757575; }
         .Example h3,.Example h4 { display:inline-block; font:bold 15px Arial; padding:0px 5px 0px 5px; border-radius:2px; color:black; margin:2px; font-style:normal; color:#333; }
         .Example h3 { background:#EE9; border:1px solid #DD8; }
         .Example h4 { background:#BDE; border:1px solid #ACD; }
         .Example a { text-decoration:underline; }      
         .Example li { padding-bottom:8px; }
         .Example ul { margin:6px 0px 0px 20px; font:13px Arial; }
         .Example .Err { margin:50px auto 10px auto; padding:5px; line-height:30px; border:1px solid black; color:red; width:800px; text-align:center; display:none; }
         .Example .Desc { margin:0px 5px 5px 5px; padding:10px; border:1px solid #dfdfdf; }
         .Example .Desc > ul { margin-left:0px; padding:0px 0px 0px 15px; clear:both; }
         .Example .Desc b { color:#0585B9; }
         .Example .Path { font:normal 12px Arial; color:#0585B9; }
         .Example .Path b { color:#D73938; }
         .Example .Path u { text-decoration:none; color:black; font-weight:bold; padding:0px 2px 0px 2px; }
         .Example .Path i { color:black; font-style:normal; font-weight:bold; }
         .Example .Xml { margin-bottom:6px; font-size:12px; color:#757575; }
         .Example .Border { margin:0px 5px 5px 5px; }
         .Example .Main { }

         /* This example special CSS  */
         .Info, .Info * { padding-top:1px!important; line-height:10px; font-size:10px; } /* Style for top right Info tag on tabber */
         .InfoTwoLines { display:inline; }
         .InfoThreeLines { display:none; }
         @media (min-width:1335px){ .InfoTwoLines { display:none; } .InfoThreeLines { display:inline; } }
         @media (max-height:800px) { 
            .Example .Desc { padding:5px;  } 
            .Example .Desc * { font-size:12px; }
            .Example .Border { margin-bottom:0px; }
            .Example h1 { font:20px Arial; padding:0px; }
            .Example h2 { display:none; }
            body { margin:0px; }
            }

         .Box { overflow:hidden; }
         .GWLow .Box * { line-height:12px; }
         .BoxTop { background:#48ABAA; border:1px solid #379C9A; color:white; padding:1px 5px 1px 5px; border-top-left-radius:2px; border-top-right-radius:2px; font-weight:bold; }
         .BoxInner { border-left:1px solid #CCC9B8; border-right:1px solid #CCC9B8; padding-left:15px; padding-right:15px; }
         .BoxInner > * { overflow:hidden; }
         .BoxBottom { background:#586980; border:1px solid #485970; color:white; padding:1px 5px 1px 5px; border-bottom-left-radius:2px; border-bottom-right-radius:2px; font-weight:bold; }

         /* This example presets some default CSS */
         .GridMain .GWGanttBoxOut,.GridMain .GSGanttBoxOut,.GridMain .GTGanttBoxOut,.GridMain .GBGanttBoxOut,.GridMain .GMGanttBoxOut { border-radius:2px; padding:0px; }
         .GridMain .GWGanttBoxIn,.GridMain .GSGanttBoxIn,.GridMain .GTGanttBoxIn,.GridMain .GBGanttBoxIn,.GridMain .GMGanttBoxIn { border-radius:2px; padding:0px; }
         .GWGanttWhiteIn { background:white; }
         .GWGanttWhiteCompleteGauge { background-color:#DDD; color:black; border-right:0px none; } 
         .GWGanttWhiteIn.GWGanttIncomplete { background-color:white; }

      </style>
      <script>
// ------------------------------------------------------------------------------------------------------------
// Called on grid loaded, used to switch the starting view
Grids.OnUpdated = function(G){
SwitchView(0,1); // Starts with Gantt view, change to SwitchView(1,1) to start with Network diagram
if(Grids.Tablet) { 
   G.NoVScroll = 1;                                     // No vertical scroll on iPad
   G.GetRowById("Tablet").Visible = 1; UpdateActions(); // Shows the actions control row on iPad and sets actual actions
   }
}
// ------------------------------------------------------------------------------------------------------------
// Switches view with informational message, now only for tablets
function SwitchViewMessage(view){
if(!Grids.Tablet) return SwitchView(view);
var G = Grids.Gantt;
if(!G.Def.Diagram.Group==!view) return;
G.ShowMessage("Changing view to "+["Gantt chart","Network diagram"][view]);
setTimeout(function(){ SwitchView(view); G.HideMessage(); },10);
}
// ------------------------------------------------------------------------------------------------------------
// Switches view between Gantt chart (view = 0) and Network diagram (view = 1)
function SwitchView(view,noshow){
var G = Grids.Gantt;
if(!noshow && !G.Def.Diagram.Group==!view) return;
G.GanttUpdate = 1;                                          // Temporary disables the Gantt to not be refreshed during grouping
var group = G.Group; if(view && (!group||group=="COMPLETE,TASK")) group = "TASK";     // For the Network diagram in this example the grid must be grouped and only in one level
var F = Grids.OnGroup; Grids.OnGroup = null;                // Temporary disables the event handler OnGroup
if(!noshow) G.DoGrouping("");                               // Ungroups grid
G.Def.Diagram.Group = view; G.Def.DiagramTask.Group = view; // Sets 1 for Network diagram
G.Def.Sum.Group = !view; G.Def.SumTask.Group = !view;       // Sets 1 for Gantt chart
G.Cols.GANTT.GanttBottom = view ? 6 : 2;                    // Sets the space under bars
var b1 = view ? "" : "Box", b2 = view ? "Box" : "";         // Replaces From/FromBox and To/ToBox in dependency tip, because Network diagram uses Box id na Gantt chart row id
G.Cols.GANTT.GanttDependencyTip = G.Cols.GANTT.GanttDependencyTip.replace("*From"+b1+"*","*From"+b2+"*").replace("*To"+b1+"*","*To"+b2+"*");
G.Cols.GANTT.GanttRunSelect = view?5:0;                     // Permits selecting Run boxes in the Network diagram view
var r = G.GetRowById("Summary"); if(noshow) r.Visible = !view; else if(view) G.HideRow(r); else G.ShowRow(r); // Hides bottom summary for Network diagram
var r = G.GetRowById("Group"); r.BarCanEdit = !view; if(!noshow) G.RefreshCell(r,"Bar"); // Low bars has sense only for Gantt chart bars, not Network diagram
if(!noshow) G.DoGrouping(group);                            // Regroups grid 
G.GanttUpdate = 0;                                          // Enables the disabled Gantt, refresh is needed    
if(!noshow) G.RefreshGantt();                               // Refreshes Gantt, especially for dependencies
var r = G.GetRowById("Tabber");
r.Gantt = view==0?1:0; r.Diagram = view==1?1:0;             // Changes the selected tab. It does it here, because standard ButtonClick action is not called
r.Changed = view==1; r.GanttChanged = view==1; r.DiagramChanged = view==1;  // Sets the tabs changed for view = 1, to be used when exporting to PDF
if(!noshow) { G.RefreshCell(r,"Gantt"); G.RefreshCell(r,"Diagram"); }
r.Info = G.Lang.Text[["Gantt","Run","GanttT","RunT"][Grids.Tablet ? view+2 : view]]; if(!noshow) G.RefreshCell(r,"Info"); // Changes the Mouse controls cell in Tabber according to the view
Grids.OnGroup = F;                                          // Restores the OnGroup event handler
return true;                                                // Suppresses default ButtonClick action for the cell
}
// ------------------------------------------------------------------------------------------------------------
// Called after language change to refresh the top information
Grids.OnLanguageSet = function(G,code){
var r = G.GetRowById("Tabber"), view = r.Diagram ? 1 : 0;
r.Info = G.Lang.Text[["Gantt","Run","GanttT","RunT"][Grids.Tablet ? view+2 : view]]; G.RefreshCell(r,"Info"); // Changes the Mouse controls cell in Tabber according to the view
}
// ------------------------------------------------------------------------------------------------------------
// Updates edit permissions according to the Tablet row
function UpdateActions(){
var G = Grids.Gantt, r = G.GetRowById("Tablet"), C = G.Cols.GANTT;
if(r.Visible){
   var cells = r.Cells; if(typeof(cells)=="string") cells = cells.split(","); // On start are the Cells string, later is parsed to array
   for(var o=null,a=null,i=0;i<cells.length;i++){ // Iterates all cells in Tablet row and searches the two actually chosen cells
      var n = cells[i];
      if(r[n] && r[n+"Radio"]==1) o = n;      // object
      else if(r[n] && r[n+"Radio"]==2) a = n; // action
      }
   if(o==null||a==null) return; // Function was called between changes
   }
else { o = "All"; a = ""; }
if(a=="Every") a = ""; // For Every does not specify the action suffix
if((o=="Flags"||o=="Constraints") && a=="Resize") { o = ""; a = ""; } // Flags and Constraints cannot be resized
if(o=="None") { o = ""; a = ""; }

// --- Vertical lines ---
var bounds = (o=="Bounds"||o=="All") && (!a||a=="Move") ? 1 : 0;
C.GanttBaseCanEdit = bounds; C.GanttFinishCanEdit = bounds;
var L = C.GanttLines.split(";");
for(var i=0;i<L.length;i++) if(L[i]) { var l = L[i].split("#"); l[0] = (l[0]&254)+bounds; L[i] = l.join("#"); }
C.GanttLines = L.join(";");
for(var i=-2;i<2;i++) G.SetGanttLine(i,null,null,null,bounds);

// --- Other objects ---
if(o=="All"){ // All objects
   var def = ",MainComplete,MainText,MainState,Main1Complete,Main1Text,Main1State,RunComplete,RunText,RunState,Resources";
   if(!a) C.GanttEdit = "All"; // All is shortcut for all actions permitted
   else if(a=="Move") C.GanttEdit = "MainMove,Main1Move,RunMove,FlagsMove,ConstraintsMove,DependencyCorrect"+def;
   else if(a=="Resize") C.GanttEdit = "MainResize,Main1Resize,RunResize"+def;
   else if(a=="New") C.GanttEdit = "MainNew,Main1New,RunNew,FlagsNew,ConstraintsNew,DependencyNew,DependencyTypes,DependencyLags"+def;
   var ed = !a||a=="Move" ? "MainMove,Main1Move" : "";
   G.Def.Sum.GANTTGanttEdit = ed; G.Def.SumTask.GANTTGanttEdit = ed;
   var ed = "Run"+a+(!a||a=="New" ? ",DependencyNew,DependencyLags,DependencyTypes" : "");
   G.Def.Diagram.GANTTGanttEdit = ed; G.Def.DiagramTask.GANTTGanttEdit = ed;
   }
else { // Particular object
   if(o=="Bounds"){ o = "DependencyCorrect"; a = ""; } // Bounds permits correcting dependencies, especially for move GanttBase
   if(o=="Dependency") {
      if(!a||a=="New") a = ",DependencyLags,DependencyTypes"; // This example permits dependency lags and types
      else { o = ""; a = ""; } // Dependencies cannot be resized or moved
      }
   C.GanttEdit = o + a; // Sets base edit permissions for all data rows
   if(o=="Main"||o=="Main1"||o=="Run") C.GanttEdit += ","+o+"Complete,"+o+"Text,"+o+"State,"+o+"Correct,Resources"; // Other actions for main bar are enabled always
   else if(o=="Flags") C.GanttEdit += ","+o+"Text";                                // Other actions for flags are enabled always
   var ed = (o=="Main"||o=="Main1")&&(!a||a=="Move") ? o+"Move" : "";              // In Gantt chart summary row permits only moving main tasks
   G.Def.Sum.GANTTGanttEdit = ed; G.Def.SumTask.GANTTGanttEdit = ed;
   var ed = o=="Main" ? "Run"+a : o=="Dependency" ? o+"New,DependencyLags,DependencyTypes" : ""; // In Network diagram summary permits only actions for runs and dependencies
   G.Def.Diagram.GANTTGanttEdit = ed; G.Def.DiagramTask.GANTTGanttEdit = ed;
   }
}
// ------------------------------------------------------------------------------------------------------------
// Generates the run box text for Network diagram
Grids.OnGetGanttRunText = function(G,row,col,run,idx,text,width,left,maxw,cls,exp){
var B = G.GetGanttRunBox(row,col,idx); // Gets the run box
if(!B.Id) return "";                   // It can be empty during creating new run box by dragging
var src = G.GetRowById(B.Id.slice(1)); // Gets the source row for the box
if(!src) return "";                    // src is empty during creating new run box by dragging
if(exp){
   if(cls[0]=="White") cls[0] = "Gray";
   return "<div style='font-size:11px;'><span style='color:white;font-weight:bold;'>"+B.id+". "+G.Translate(row,"SECTION",(Get(row,"SECTION"))+" - "+G.Translate(src,"SECTION",Get(src,"SECTION")))+"</span><br/>"
      +"<span style='font-size:9px;'>"
      +"<span>"+DateToString(B.Start,"sy*stm")+"</span><br/>"
      +"<span>"+DateToString(B.End,"sy*stm")+"</span><br/>"
      +(B.Duration? DateToString(B.Duration,"eh"):"<span style='color:blue;font-size:10px;'>Milestone</span>")+" <span style='color:blue;'>$"+NumberToString(G.GetGanttPrice(row,col,B.id),",0")+"</span><br/>"
      +"<span style='color:"+(B.Complete==100? "#B2FA70":(B.Complete==0? "#FC8":"#88C8FF"))+";'>"+B.Complete+"%</span> "
      +"</span>"
      +"<span style='color:white;'>"+(B.Resources? B.Resources.replace(/\#/g,"; ").replace("Support","Sup").replace("Sales","Sal").replace("Management","Mgm").replace("Development","Dev").replace("Material","Mat"):"")+"</span>";
   }
var s = "<div class='Box'>"
   + "<div class='BoxTop'>"+B.id+". "+G.Translate(row,"SECTION",(Get(row,"SECTION"))+" - "+G.Translate(src,"SECTION",Get(src,"SECTION")))+"</div>"
   + "<div class='BoxInner'>"
   + "<div>"+DateToString(B.Start,"sy*stm")+"</div>"
   + "<div>"+DateToString(B.End,"sy*stm")+"</div>"
   + "<div>"+(B.Duration ? DateToString(B.Duration,"eh") : "<span style='color:blue;font-size:10px;'>Milestone</span>")+"<span style='padding-left:6px;color:blue;'>$"+NumberToString(G.GetGanttPrice(row,col,B.id),",0")+"</span></div>"
   + "</div>"
   + "<div class='BoxBottom'>"
      +"<span style='color:"+(B.Complete==100?"#B2FA70":(B.Complete==0?"#FC8":"#88C8FF"))+";'>"+B.Complete+"%</span> "
      +(B.Resources?B.Resources.replace(/\#/g,"; ").replace("Support","Sup").replace("Sales","Sal").replace("Management","Mgm").replace("Development","Dev").replace("Material","Mat"):"")
   +"</div>"
   + "</div>";
var bw = G.GetBodyWidth(2)-100; // Width of the right section
if(!bw) bw = 400;               // bw is null before the grid is rendered
if(width<bw) return "<div>"+s+"</div>"; // OK, the box is visible whole

// --- Repeats the content more times for too wide boxes ---
var q = "";
if(left<0)  { q += "<td style='width:"+(-left)+"px;'>&nbsp;</td>"; width += left; } // Subtracts the left invisible part
if(width>maxw) width = maxw;                                                        // Subtracts the right invisible part
for(;width>0;width-=bw) q += "<td style='width:"+bw+"px;'>"+s+"</td>";              
return "<div style='padding:1px;'><table cellspacing='0' cellpadding='0'><tr>"+q+"</tr></table></div>";
}
// ------------------------------------------------------------------------------------------------------------
// Modifies dependency thickness for Network diagram
Grids.OnGetDependency = function(G,row,col,dep,start,end,dur){
dep[6] = row.Def.Name=="Diagram" || row.Def.Name=="DiagramTask" ? 20 : 0;
}
// ------------------------------------------------------------------------------------------------------------
// Restricts ungrouping and grouping by two columns in Network diagram
Grids.OnGroup = function(G,group){
if(G.Rows.Tabber.Diagram && (!group||group=="COMPLETE,TASK")) {
   alert(G.Lang.Text.GroupAlert);
   return true;
   }
}
// ------------------------------------------------------------------------------------------------------------
// To specify grouping by Complete, differs only 100%, 0% and others
Grids.OnGetSortValue = function(G,row,col,val,desc,group){
if(group && col=="COMPLETE") {
   if(val=="100%") return 100;
   if(val=="0%") return 0;
   return "50";
   }
return val;
}
// ------------------------------------------------------------------------------------------------------------
// Corrects all dependencies for Run boxes after some change
// It is done by API event, because in this example the Run boxes themselves are not corrected, therefore not checked for correcting
var TM = null;
Grids.OnGanttRunBoxChanged = function(G,B,O,chg){
if(!(chg&30)) return; // Ignores only changes in box attributes
if(TM) clearTimeout(TM);
TM = setTimeout(function(){
   TM = null;
   if(G.Cols.GANTT.GanttCorrectDependencies==2) G.ShowMessageTime(G.Lang.Text.RunCorrect,0,function(result){  // result = -2 esc, -1 enter, 1 yes, 2 no, 3 always, 4 never
      if(result==3||result==4) { G.Cols.GANTT.GanttCorrectDependencies = result==3?1:0; G.RecalculateRows([G.GetRowById('Project')],1); }
      if(result==3||result==1||result==-1) G.ActionCorrectAllDependencies(); 
      },["Yes","No","Always","Never"]);
   else if(G.Cols.GANTT.GanttCorrectDependencies==1) G.ActionCorrectAllDependencies();
   },100);
}
// ------------------------------------------------------------------------------------------------------------
// Called after moved visual progress line, to change the progress calculation
Grids.OnGanttLineChanged = function(G,idx,d1,d2,cls,edit,od1,od2,ocls,oedit){
if(idx==1 && d1) G.SetValue(G.GetRowById("Project"),"Progress",d1,1);
}
// ------------------------------------------------------------------------------------------------------------
// Used to show tip on Gantt header row
// For Gantt chart rows and objects use rather OnGanttTip instead
Grids.OnTip = function(G,row,col,tip,clientx,clienty,x,y){
if(col=="GANTT" && row.id=="id") { // Gantt header row
   var A = G.GetGanttHeaderXY(row,col,x,y); if(!A) return;
   tip = "<b>"+G.Lang.GanttUnits[A.Units]+"</b><br>" + DateToString(A.Start,"'<b>'*ly*'</b>'*lts") + " - " + DateToString(A.End,"'<b>'*ly*'</b>'*lts") + "<br>" + G.Lang.Text.HeaderTip;
   }
return tip;
}
// ------------------------------------------------------------------------------------------------------------
// Called when NoVScroll / NoHScroll is set automatically due small window size, disables the checkbox for manual change of NoVScroll / NoHScroll
// First time it hides resource usage rows. Sets OnceLimit custom attribute to not run it again if a user shows the resource rows again
Grids.OnLimitScroll = function(G,clr,noh,nov){ 
if(G.Def.Resource.GANTTGanttAvailability&&!clr&&!G.OnceLimit){
   G.OnceLimit = 1;
   G.Def.Resource.GANTTGanttAvailability = "";
   var F = G.GetRows(G.Foot); G.StartUpdate();
   for(var i=0;i<F.length;i++) G.HideRow(F[i]); 
   G.EndUpdate();
   G.Rows.Controls.Chart = ""; G.RefreshCell(G.Rows.Controls,"Chart");
   return -1;
   }
G.SetAttribute(G.Rows.Controls,"Win","CanEdit",clr,1); 
var tip = clr?"Disable grid scrollbars and use page scrollbars":"Used page scrollbars because browser window is too small to show this example with its own scrollbars";
G.SetAttribute(G.Rows.Controls,"Win","Tip",tip,1); 
G.SetAttribute(G.Rows.Controls,"WinLabelRight","Tip",tip,1); 
}
// ------------------------------------------------------------------------------------------------------------
// Called on importing xlsx, to mirror CLASS/CLASS1 cells to GanttClass, because the cell value is calculated from it
Grids.OnImportCell = function(G,imrow,imcol,row,col){ 
if(col=="CLASS") row.GANTTGanttClass = row[col];
else if(col=="CLASS1") row.GANTTGanttClass1 = row[col];
}
// ------------------------------------------------------------------------------------------------------------

      </script>
      <center class="Path"><script>document.write(location.href.replace(/(.*)(\/ExamplesPDF\/)([^\/_]+)_([^\/_]+)\/([^\/]+)$/,"$2<b>$3</b>_<i>$4</i>/$5").replace(/([^<]|^)(\/|\.)/g,"$1<u>$2</u>"));</script></center>
      <h1>Interactive Gantt chart and Network diagram</h1>
      <div class="Err">
         <script> if(location.protocol=="file:") document.write("<style>.Example .Desc, .Example .Border {display:none;} .Example .Err { display:block; } </style>"); </script>
         Do <b>not</b> run this file locally!<br />Run it from your local or remote web http server where is installed IIS and ASP.NET (1.0, 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, ...).<br>
      </div>
      <div class="Border">
         <div class="Main">
            <bdo Sync="1" Debug="Check" DebugCheckIgnore="Res" 
               Layout_Url="GanttDef.xml"
               Data_Url="GanttData.xml"
               ExportPDF_Url="../ExportPdf.aspx" ExportPDF_Type="Settings,Expanded,Selected,Changes,Gantt,NoUpload" ExportPDF_Param_Source="Gantt/GanttExportPDF.html"
               ></bdo>
         </div>
      </div>
      <div class="Desc">
         <button onclick='Grids[0].ActionExportPDF();'>Print to PDF</button>
         <button onclick='Grids[0].ActionPrint();'>Print to printer</button>
         <button onclick='Grids[0].ActionExport()'>Export to XLSX</button>
      </div>

      <!-- Google Analytics code run once for trial -->
      <script>
         var TGTrial = document.cookie.match(/TGPDFCS\s*=\s*(\d+)/), TGIndex = 2048;
         if(!TGTrial||!(TGTrial[1]&TGIndex)) setTimeout(function(){
            var n = "RunPdfCSGantt", d = (new Date((new Date).getTime()+31536000000)).toUTCString(); document.cookie = "TGPDFCS="+((TGTrial?TGTrial[1]:0)|TGIndex)+";expires="+d;
            var u = document.cookie.match(/TGPDFUsed\s*=\s*(\d+)/); u = u ? u[1]-0+1 : 1; if(u<=11) document.cookie = "TGPDFUsed="+u+";path=/;expires="+d;
            var s = "<div style='width:0px;height:0px;overflow:hidden;'><iframe src='http"+(document.location.protocol=="https"?"s":"")+"://www.treegrid.com/Stat/GA.html?productName="
                 +(u==1||u==3||u==5||u==10?"UsedPdf"+u:n)+"' onload='var T=this;setTimeout(function(){document.body.removeChild(T.parentNode.parentNode);},1000);'/></div>";
            var F = document.createElement("div"); F.innerHTML = s; document.body.appendChild(F);
            },100);
      </script>
   </body>
</html>